#include "CFrameListener.hpp"

float CFrameListener::dt = 1000/MAX_FPS;
CFrameListener * CFrameListener::singleton=NULL;

CFrameListener::CFrameListener():ExampleFrameListener(CAplicacion::getSingleton()->getRenderWindow() , CAplicacion::getSingleton()->getCamera())
{
	singleton = this;

	this->errorFisica=0;
	this->velocidadFisica = 2;
	this->mediaFPS = MAX_FPS / velocidadFisica;
	this->numPasos = mediaFPS / 15.0f; //Cada 15 fps un paso
	this->tiempoPaso = 1.0f/mediaFPS;

	CAplicacion::getSingleton()->getNxScene()->setTiming(tiempoPaso / numPasos, numPasos, NX_TIMESTEP_FIXED);

	MaterialManager::getSingleton().setDefaultTextureFiltering(TFO_ANISOTROPIC);
	MaterialManager::getSingleton().setDefaultAnisotropy(8);
}

CFrameListener::~CFrameListener()
{

}

bool CFrameListener::frameStarted(const FrameEvent& evt)
{
	//Empezamos a contar
	empiezaFrame = SDL_GetTicks();

	CAplicacion::getSingleton()->mSoundManager->update(evt.timeSinceLastFrame);

	//Llamamos al padre, por tante no es un override realmente
	if (!ExampleFrameListener::frameStarted( evt )) return false;

	//Empieza fisica
	if(!errorFisica)
	{
		CAplicacion::getSingleton()->getNxScene()->simulate(tiempoPaso);
		CAplicacion::getSingleton()->getNxScene()->flushStream();
	}

	return true;
}

bool CFrameListener::frameEnded(const FrameEvent& evt)
{
	//Fin fisica
	CAplicacion::getSingleton()->getNxScene()->fetchResults(NX_ALL_FINISHED, true , &errorFisica);
	if(errorFisica) cout << "No dio tiempo a calcular la fisica en este frame, se hara en el siguiente" << endl;

	
	refrescarTodo(evt.timeSinceLastFrame);

	updateStats();
	terminaFrame = SDL_GetTicks();
	dt = terminaFrame - empiezaFrame;
	SDL_Delay(max((1000/MAX_FPS) - dt , 0.0f));
	terminaFrame = SDL_GetTicks();
	dt = terminaFrame - empiezaFrame;
	return true;
}

void CFrameListener::refrescarTodo(Real tiempoDesdeUltimoFrame)
{
	//********************

	if(CUtiles::getPhysXAction() == 1 )
	{
		CAplicacion::getSingleton()->CreateCubeFromEye(2.0f);
	}
	else if(CUtiles::getPhysXAction() == 2 )
	{
		CAplicacion::getSingleton()->CreateStack(4);
	}
	else if(CUtiles::getPhysXAction() == 3 )
	{
		CAplicacion::getSingleton()->CreateTower(5);
	}
	CUtiles::setPhysXAction(0);

	//********************
	
	/*
	 * Sincronizamos el render y la fisica
	 */
	int nbActors = CAplicacion::getSingleton()->getNxScene()->getNbActors();
	NxActor** actors = CAplicacion::getSingleton()->getNxScene()->getActors();
	while(nbActors--)
	{
		NxActor * actor = *actors++;
		if(actor->userData != NULL)
		{
			CEntidad * entidad = (CEntidad *)actor->userData;
			if(entidad != NULL && entidad->getActor()->isDynamic())
			{
				entidad->refrescar(tiempoDesdeUltimoFrame);
			}
		}
	}
}

CFrameListener * CFrameListener::getSingleton()
{
	return singleton;
}
